/**
 * B.A.M. - Boulders and Money
 * Joshua Jung (jjung37)
 * CS 450 UIC
 * w/ John Bell
 */
#include "Keyboard.h"
#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>

using namespace std;

// Internal variables for use by the following methods.
pthread_t thread;
int kb_key;
pthread_mutex_t key_m;
bool kb_keyRead;
pthread_mutex_t keyRead_m;

/**
 * This starts up the thread which reads keyboard input.
 */
void kb_start()
{
    // This sets up the appropriate mode so that keys
    // can be read without pressing ENTER and without
    // echoing to the display
    struct termios tty;
    tcgetattr(fileno(stdout), &tty);
    tty.c_lflag &= ~(ICANON);
    tty.c_lflag &= ~(ECHO);
    tcsetattr(fileno(stdout), TCSANOW, &tty);

    kb_keyRead = true;

    pthread_create(&thread, NULL, kb_run, NULL);
}

/**
 * This is the primary loop for the keyboard data.
 */
void *kb_run(void *message)
{
    while (1)
    {
        int c;

        c = getchar();

        kb_setChar(c);

        pthread_mutex_lock(&keyRead_m);
        kb_keyRead = false;
        pthread_mutex_unlock(&keyRead_m);
    }
}

/**
 * This is the internal method that sets the currently pressed character
 */
void kb_setChar(int c)
{
    pthread_mutex_lock(&key_m);
    kb_key = c;
    pthread_mutex_unlock(&key_m);
}

/**
 * This returns the currently pressed character if it has not already
 * been read.
 */
int kb_getChar()
{
    int c = 0;

    if (kb_keyRead == false)
    {
        pthread_mutex_lock(&key_m);
        c = kb_key;
        pthread_mutex_unlock(&key_m);
        
        pthread_mutex_lock(&keyRead_m);
        kb_keyRead = true;
        pthread_mutex_unlock(&keyRead_m);
    }

    return c;
}
